/***************************************************************************************************
  *Copyright(C),2010-2016,Sumscope
  *FileName	:  TinyString.cpp
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2020/06/12
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#include "TinyString.h"
namespace qb{
	namespace base{
		TinyString::~TinyString()
		{
			destroy();
		}

		TinyString::TinyString(const char* str) :m_data(nullptr)
		{
			assign(str, -1);
		}

		TinyString::TinyString(const char* str, int len) : m_data(nullptr)
		{
			assign(str, len);
		}

		TinyString::TinyString(const std::string& str) : m_data(nullptr)
		{
			assign(str.c_str(), str.size());
		}

		TinyString::TinyString(const ThisType& str) : m_data(nullptr)
		{
			assign(str.c_str(), str.size());
		}

		TinyString::TinyString(ThisType&& str) : m_data(str.m_data)
		{
			str.m_data = nullptr;
		}

		TinyString::TinyString() : m_data(nullptr)
		{

		}

		qb::base::TinyString& TinyString::operator=(ThisType& str)
		{
			assign(str.c_str(), str.size());
			return *this;
		}

		TinyString& TinyString::operator=(ThisType&& str)
		{
			std::swap(m_data, str.m_data);
			return *this;
		}

		TinyString& TinyString::operator=(const char* str)
		{
			assign(str, -1);
			return *this;
		}

		TinyString& TinyString::operator+=(const ThisType& str)
		{
			assign_plus(c_str(), size(), str.c_str(), str.size());
			return *this;
		}

		TinyString& TinyString::operator+=(const char* str)
		{
			assign_plus(c_str(), size(), str, -1);
			return *this;
		}

		int TinyString::bytes() const
		{
			if (m_data == nullptr || istiny())return 4;
			int len = size();
			return len >= TinyLength ? (sizeof(const char*) + len + 3) : (sizeof(const char*) + len + 2);
		}

		bool TinyString::assign_plus(const char* str, int len, const char* post, int postLen)
		{
			len = str ? (len <= 0 ? strlen(str) : len) : 0;
			postLen = post ? (postLen <= 0 ? strlen(post) : postLen) : 0;
			int total = len + postLen;
			if (total <= 0)
			{
				destroy();
				m_data = nullptr;
				return true;
			}
			if (total <= 3)
			{
				char raw[4] = { 0, 0, 0, 0 };
				if (len > 0){ memcpy(raw, str, len); }
				if (postLen > 0){ memcpy(raw + len, post, postLen); }
				raw[3] = 0;
				destroy();
				memcpy(m_raw, raw, 4);
				return true;
			}
			total = total >= MaxLength ? MaxLength : total;
			int extra = 0;
			char* data = new (std::nothrow) char[extra + total + 1];
			char* dest = data + extra;
			char* end = data + extra + total;
			if (len > 0){ memcpy(dest, str, len); }
			if (postLen > 0){ memcpy(dest + len, post, postLen); }
			*end = '\0';
			set_length(data, total);
			destroy();
			set_pointer(data);
			return true;
		}

		bool TinyString::assign(const char* str, int len)
		{
			if (len < 0)len = str ? strlen(str) : 0;
			if (len <= 0)
			{
				destroy();
				m_data = nullptr;
				return true;
			}
			else if (len <= 3){
				char raw[4] = { 0, 0, 0, 0 };
				memcpy(raw, str, len);
				raw[3] = 0;
				destroy();
				memcpy(m_raw, raw, 4);
				return true;
			}
			len = len >= MaxLength ? MaxLength : len;
			int extra = 0;
			char* data = new (std::nothrow) char[extra + len + 1];
			if (data)
			{
				memcpy(data + extra, str, len);
				data[extra + len] = 0;
				set_length(data, len);
				destroy();
				set_pointer(data);
				return true;
			}
			return false;
		}
	}//namespace base;
}//namespace ss;
